package ichubelastic

import (
	"context"
	"encoding/json"
	"fmt"
	"gitee.com/ichub/webcli/common/base/baseconfig"
	"gitee.com/ichub/webcli/common/base/basedto"
	"gitee.com/ichub/webcli/common/base/baseutils/jsonutils"
	"github.com/olivere/elastic"
	"github.com/sirupsen/logrus"
	"reflect"
	"testing"
	"time"
)

var cli = NewElasticClient()

func init() {
	var clientDto = baseconfig.NewElasticClientDto()
	clientDto.URL = "http://192.168.14.58:9200"
	clientDto.Username = "elastic"
	clientDto.Password = "123456"
	cli.ClientDto = clientDto

}

// https://www.cnblogs.com/root-123/p/16572186.html
func Open() (*elastic.Client, error) {
	return cli.Open()
}

func Test0001_elasticCreateIndex(t *testing.T) {
	client, _ := Open()
	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 首先检测下weibo索引是否存在
	exists, err := client.IndexExists("weibo").Do(ctx)

	if err != nil {
		logrus.Info(err)
		// Handle error
		panic(err)
	}
	if !exists {
		// weibo索引不存在，则创建一个
		_, err := client.CreateIndex("weibo").BodyString(mapping).Do(ctx)
		if err != nil {
			// Handle error
			panic(err)
		}
	}
}

type Weibo struct {
	basedto.BaseEntity
	User     string                `json:"user"`               // 用户
	Message  string                `json:"message"`            // 微博内容
	Retweets int                   `json:"retweets"`           // 转发数
	Image    string                `json:"image,omitempty"`    // 图片
	Created  time.Time             `json:"created,omitempty"`  // 创建时间
	Tags     []string              `json:"tags,omitempty"`     // 标签
	Location string                `json:"location,omitempty"` //位置
	Suggest  *elastic.SuggestField `json:"suggest_field,omitempty"`
}

func NewWeibo() *Weibo {
	var w = &Weibo{}
	w.InitProxy(w)
	return w
}

func Test0002_elasticInsertIndex(t *testing.T) {

	client, _ := Open()
	// 创建创建一条微博
	msgWeibo := Weibo{User: "olivere", Message: "打酱油的一天", Retweets: 0}

	// 使用client创建一个新的文档
	put1, err := client.Index().
		Index("weibo").          // 设置索引名称
		Id("1").                 // 设置文档id
		BodyJson(msgWeibo).      // 指定前面声明的微博内容
		Do(context.Background()) // 执行请求，需要传入一个上下文对象
	if err != nil {
		// Handle error
		panic(err)
	}
	fmt.Printf("文档Id %s, 索引名 %s\n", put1.Id, put1.Index)
}

const mapping = `
{
  "mappings": {
    "properties": {
      "user": {
        "type": "keyword"
      },
      "message": {
        "type": "text"
      },
      "image": {
        "type": "keyword"
      },
      "created": {
        "type": "date"
      },
      "tags": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_point"
      },
      "suggest_field": {
        "type": "completion"
      }
    }
  }
}`

func Test0003_elasticQueryIndex(t *testing.T) {
	client, _ := Open()
	result, err := client.Get().
		Index("weibo").          // 指定索引名
		Id("1").                 // 设置文档id
		Do(context.Background()) // 执行请求
	if err != nil {
		// Handle error
		panic(err)
	}
	if result.Found {
		fmt.Printf("文档id=%s 版本号=%d 索引名=%s\n", result.Id, result.Version, result.Index)
	}

	msg2 := Weibo{}
	// 提取文档内容，原始类型是json数据
	data, _ := result.Source.MarshalJSON()
	// 将json转成struct结果
	json.Unmarshal(data, &msg2)
	msg2.InitProxy(msg2)
	// 打印结果
	fmt.Println("msg=", msg2.ToPrettyString())
	logrus.Info(jsonutils.ToJsonPretty(result))
}

type Article struct {
	Title   string    // 文章标题
	Content string    // 文章内容
	Author  string    // 作者
	Created time.Time // 发布时间
}

func Test0004_elasticQueryIndex(t *testing.T) {
	client, _ := Open()
	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 创建term查询条件，用于精确查询
	termQuery := elastic.NewTermQuery("Author", "tizi")

	searchResult, err := client.Search().
		Index("weibo").        // 设置索引名
		Query(termQuery).      // 设置查询条件
		Sort("Created", true). // 设置排序字段，根据Created字段升序排序，第二个参数false表示逆序
		From(0).               // 设置分页参数 - 起始偏移量，从第0行记录开始
		Size(10).              // 设置分页参数 - 每页大小
		Pretty(true).          // 查询结果返回可读性较好的JSON格式
		Do(ctx)                // 执行请求

	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("查询消耗时间 %d ms, 结果总数: %d\n", searchResult.TookInMillis, searchResult.TotalHits())

	if searchResult.TotalHits() > 0 {
		// 查询结果不为空，则遍历结果
		var b1 Article
		// 通过Each方法，将es结果的json结构转换成struct对象
		for _, item := range searchResult.Each(reflect.TypeOf(b1)) {
			// 转换成Article对象
			if t, ok := item.(Article); ok {
				fmt.Println(t.Title)
			}
		}
	}
}
